package ice.server.comm;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * @author zhangrb
 * 基础service的实现，所有service类都要继承此类
 * @param <T>
 * @param <ID>
 */
public abstract class BaseServiceImpl<T, ID extends Serializable> extends BaseBatchServiceImpl<T> implements CommService<T, ID> {

	@Resource(name="commRepository")
	private CommRepositoryImpl commRepositoryImpl;

	public abstract CommRepository<T, ID> getRepository();
	
	public abstract ID getIdenty(T t);

	public T get(ID id) {
		return getRepository().findById(id).get();
	}
	
	public List<T> findAll() {
		return getRepository().findAll();
	}
	
	private Sort makeSort(Map<String, Object>... pm) {
		List<Order> ol = new ArrayList<Order>();
		for (Map<String, Object> m : pm) {
			for (Map.Entry<String, Object> order : m.entrySet()) {
				if(StringUtils.isEmpty(order.getKey())) {
					continue;
				}
				if(!order.getKey().startsWith(Constants.ORDERBY)) {
					continue;
				}
				String col = order.getKey().replaceFirst(Constants.ORDERBY, "");
				Order o = new Order(Direction.fromString(order.getValue().toString()), col);
				ol.add(o);
			}
		}
		return Sort.by(ol);
	}

	private Specification<T> makeCluase(Map<String, Object>... pm) {
		Specification<T> ss = null;
		for (Map<String, Object> m : pm) {
			Specification<T> spec = CommSpecification.product(m);
			if(ss == null) {
				ss = Specification.where(spec);
				continue;
			}
			ss= ss.or(spec);
		}
		return ss;
	}
	
	public List<T> find(Map<String, Object>... pm) {
		Sort sort = makeSort(pm);
		Specification<T> spec = makeCluase(pm);
		return getRepository().findAll(spec, sort);
	}

	public Page<T> findPage(Map<String, Object>... pm) {
		Sort sort = makeSort(pm);
		int page = getPage(pm);
		int rows = getRows(pm);
		Pageable p = buildPageRequest(page, rows, sort);
		Specification<T> spec = makeCluase(pm);
		return getRepository().findAll(spec, p);
	}
	
	private int getPage(Map<String, Object>... pm) {
		for (Map<String, Object> map : pm) {
			for (Map.Entry<String, Object> p : map.entrySet()) {
				if(Constants.PAGE.equals(p.getKey())) {
					String val = p.getValue()==null?null:p.getValue().toString();
					return StringUtils.isEmpty(val) ? 0 : Integer.parseInt(val);
				}
			}
		}
		return 0;
	}
	
	private int getRows(Map<String, Object>... pm) {
		for (Map<String, Object> map : pm) {
			for (Map.Entry<String, Object> p : map.entrySet()) {
				if(Constants.ROWS.equals(p.getKey())) {
					String val = p.getValue()==null?null:p.getValue().toString();
					return StringUtils.isEmpty(val) ? 0 : Integer.parseInt(val);
				}
			}
		}
		return 10;
	}
	
	//构建PageRequest
    private PageRequest buildPageRequest(int page, int rows, Sort s) {
    	return PageRequest.of(page, rows, s);
    }

	public ID save(T t) {
    	t = getRepository().save(t);
		return getIdenty(t);
	}

	public boolean save(Collection<T> c) {
		getRepository().saveAll(c);
		return true;
	}

	public boolean delete(ID id) {
    	getRepository().deleteById(id);
		return true;
	}

	public boolean delete(List<ID> l) {
    	for (ID id : l) {
    		delete(id);
		}
		return true;
	}

    @SuppressWarnings("unchecked")
	public boolean delete(Map<String, Object> pm) {
		List<T> l = find(pm);
		getRepository().deleteInBatch(l);
		return true;
	}

	public long cnt(Map<String, Object>... pm) {
		Specification<T> spec = makeCluase(pm);
		try {
			
		}catch (Exception e) {
			e.printStackTrace();
		}
		return getRepository().count(spec);
	}

	/**
	 * 按指定的条件进行分页查询
	 *
	 * @author : 张美景
	 * @date : 2019.05.08 13:24
	 * @param pm 查询条件，每个map中的条件采用and拼接
	 * ，可以传多个map对象，用 or 进行拼接<br>
	 * <strong>如要按字段排序,请在字段名称加上orderby_前缀，作为可以，value填写asc或desc</strong>
	 * <br>
	 * pm 中必须包含2组键值对，<strong>e.g.</strong>{"page":2,"rows":10}
	 * @return 符合bootstrap框架的分页数据
	 */
	@SuppressWarnings({"unchecked", "varargs"})
	public Map<String, Object> searchByPage(Map<String, Object> ... pm) {
		Map<String, Object> result = new HashMap<>();
		if(pm == null || pm.length == 0 || CollectionUtils.isEmpty(pm[0])){

			result.put("total", 0);
			result.put("rows", new ArrayList<>());
			result.put("page", 0);

		}

		Page<T> p = findPage(pm);

		List<T> list = p.getContent();

		//将数据进行加工处理
		handleSearchResult(list);
		result.put("total", p.getTotalElements());
		result.put("rows", p.getContent());
		result.put("page", p.getNumber());
		return result;

	}

	/**
	 * 将数据进行加工处理（需要子类重写这个方法）
	 *
	 * @author : 张美景
	 * @date : 2019.05.08 13:24
	 * @param data 要加工的数据
	 */
	protected void handleSearchResult(List<T> data){ }


	/**
	 * 功能描述:〈根据id‘进行删除 真实删除〉
	 * @param ids
	 * @return : com.lesu.safety.comm.common.BaseOperateResult
	 * @author : 沈明可
	 * @date : 2019/5/10 16:26
	 * User :
	 */
	public  BaseOperateResult deleteByList(String ids){
		if (!StringUtils.isEmpty(ids)) {
			List<ID> list = Arrays.asList(ids.split(",")).stream().map(s -> (ID)s).collect(Collectors.toList());
			return BaseOperateResult.delete(delete(list));
		} else {
			return BaseOperateResult.warning("no selectors");
		}
	}

	/**
	 * 按条件查询单条数据
	 * @author zhangrb
	 * @user all
	 * @date 2019-8-2
	 * @param pm 查询条件map
	 * @return 查询结果
	 */
	public T findSingle(Map<String, Object>... pm){
		List<T> l = find(pm);
		return l.isEmpty() ? null : (T)l.get(0);
	}

	public List<Map<String, Object>> searchByJPQLModel(JPSQLModel jm) {
		return commRepositoryImpl.searchByJPQLModel(jm);
	}

	public Page<Map<String, Object>> searchByJPQLModel(JPSQLModel jm, Pageable p) {
		return commRepositoryImpl.searchByJPQLModel(jm, p);
	}
}
